package org.optaplanner.examples.cloudbalancing.app;

import org.optaplanner.core.api.solver.Solver;
import org.optaplanner.core.api.solver.SolverFactory;
import org.optaplanner.examples.cloudbalancing.config.CloudBalancingDBConfig;
import org.optaplanner.examples.cloudbalancing.domain.CloudBalance;
import org.optaplanner.examples.cloudbalancing.domain.CloudComputer;
import org.optaplanner.examples.cloudbalancing.domain.CloudProcess;
import org.optaplanner.examples.cloudbalancing.service.ComputerService;
import org.optaplanner.examples.cloudbalancing.service.ProcessService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.List;

/**
 * @author andaolong
 * @time 2021/3/25-8:58
 * 这个类，是自己写的，用来把cloudBalancing里面的核心逻辑抽取出来，用尽量少的类实现排程的目的
 */
public class CloudBalancingMain {

    public static void main(String[] args) {
        //通过配置的xml文件，构造求解器
        SolverFactory<CloudBalance> solverFactory = SolverFactory.createFromXmlResource(
                "org/optaplanner/examples/cloudbalancing/solver/cloudBalancingSolverConfig.xml");
        Solver<CloudBalance> solver = solverFactory.buildSolver();
        System.out.println("通过配置的xml文件，构造求解器");

        //加载一个4机器12进程的云平衡例子
        //主要就是这里输出载入的时候跟那一大团代码搞在了一起
        //这里将初始数据从数据库载入，从而与无关代码解耦
        //CloudBalance unsolvedCloudBalance = new CloudBalancingGenerator().createCloudBalance(4, 12);
        CloudBalance unsolvedCloudBalance = getUnassignment();
        System.out.println("这里改为从数据库获取初始数据，对solution进行初始化");

        //启动引擎求解问题
        CloudBalance solvedCloudBalance = solver.solve(unsolvedCloudBalance);
        System.out.println("通过引擎求解问题");

        //输出结果
        System.out.println(
                "\nSolved cloudBalance with computers and processes:\n"
                        + "求解结果为:\n"
                        + toDisplayString(solvedCloudBalance));
        System.out.println("最后分数为："+solvedCloudBalance.getScore());
    }

    //输出结果的方法
    public static String toDisplayString(CloudBalance cloudBalance) {
        //新建一个StringBuilder，相对于String的好处是可以持续增加字符串长度而不用重新分配空间
        StringBuilder displayString = new StringBuilder();
        //遍历云平衡的进程，获取到给每个进程分配的机器
        for (CloudProcess process : cloudBalance.getProcessList()) {
            CloudComputer computer = process.getComputer();
            //然后将分配的机器输出
            displayString.append("  ")
                    .append("进程" + process.getLabel()).append(" 分配的机器是-------> ")
                    .append(computer == null ? null : computer.getLabel()).append("\n");
        }
        return displayString.toString();
    }

    //从数据库获取到computer和process的初始数据填入solution中
    protected static CloudBalance getUnassignment() {

        ApplicationContext context =
                new AnnotationConfigApplicationContext(CloudBalancingDBConfig.class);
        ComputerService computerService= context.getBean("computerService", ComputerService.class);
        ProcessService processService= context.getBean("processService", ProcessService.class);
        List<CloudComputer> computerList = computerService.getComputerList();
        List<CloudProcess> processList = processService.getProcessList();
        CloudBalance unAssignment = new CloudBalance(0, computerList, processList);

        return unAssignment;
    }
}
